import { SimulateController } from "./Controller";
import { cloneDeep } from "lodash";
import { SimFrameToSubChannel, SubWinName } from "./types/Win";
import { InfoLevel, SimulateStatusType, BtnValue, headerBtns, SignalType } from "./_";
import { HiddenStatus } from "./types/Controller";

export default class ToolbarService {

  controller: SimulateController;
  status = SimulateStatusType.none;

  beginTime = Date.now() + 8 * 60 * 60 * 1000;
  lastBeginTime = 0;
  lastBeginTimeStamp = 0;
  lastEndTime = 0;
  lastEndTimeStamp = 0;
  lastUpdateTime = 0;
  initEndTime = 0;
  firstStep = true;

  signalList: SignalType[] = [];
  signalValue = "";
  speed = 95;
  simSpeedMin = 1;
  simSpeedMax = 100;
  isDiagramAutoSwitch = false;
  finishTimout: NodeJS.Timeout | undefined = undefined

  constructor(controller: SimulateController) {
    this.controller = controller as SimulateController;
  }

  set statusChange(v: SimulateStatusType) {
    console.log("statusChange: ", v);
    this.status = v;
    this.controller.winService.sendInfoToSubWins({ type: SimFrameToSubChannel.SimStatusChange, data: v });
  }

  serviceInit() {
    this.signalList.length = 0;
    this.statusChange = SimulateStatusType.none;
    this.signalValue = "";
    this.beginTime = Date.now() + 8 * 60 * 60 * 1000;
    this.firstStep = true;
    if (this.finishTimout) {
      clearTimeout(this.finishTimout);
      this.finishTimout = undefined;
    }
  }

  getVisibleButtons() {
    const btns = cloneDeep(headerBtns);
    const buttons = btns.filter((i) => {
      i.isDisabled = false;
      switch (i.value) {
        case BtnValue.SIMULATION_INIT:
          if ([SimulateStatusType.running, SimulateStatusType.initing, SimulateStatusType.ready, SimulateStatusType.stop, SimulateStatusType.pause, SimulateStatusType.checking].includes(this.status)) {
            i.isDisabled = true;
          }
          break;
        case BtnValue.SIMULATION_START:
          i.isVisible = !([SimulateStatusType.running, SimulateStatusType.stop, SimulateStatusType.pause].includes(this.status));
          if ([SimulateStatusType.running, SimulateStatusType.initing, SimulateStatusType.none, SimulateStatusType.finish, SimulateStatusType.checking].includes(this.status)) {
            i.isDisabled = true;
          }
          break;
        case BtnValue.SIMULATION_PAUSE:
          i.isVisible = this.status === SimulateStatusType.running;
          if ([SimulateStatusType.initing, SimulateStatusType.ready, SimulateStatusType.stop].includes(this.status)) {
            i.isDisabled = true;
          }
          break;
        case BtnValue.SIMULATION_CONTINUE:
          i.isVisible = (this.status === SimulateStatusType.pause || this.status === SimulateStatusType.stop);
          if ([SimulateStatusType.initing, SimulateStatusType.ready].includes(this.status)) {
            i.isDisabled = true;
          }
          break;
        case BtnValue.STEP_ONE:
          if ([SimulateStatusType.checking, SimulateStatusType.initing, SimulateStatusType.none, SimulateStatusType.finish, SimulateStatusType.running].includes(this.status)) {
            i.isDisabled = true;
          }
          break;
        case BtnValue.SIMULATION_FINISH:
          if ([SimulateStatusType.none, SimulateStatusType.finish, SimulateStatusType.initing].includes(this.status)) {
            i.isDisabled = true;
          }
          break;
      }
      return i.isVisible;
    });
    console.log('toolbar btn status: ', this.status);
    return buttons;
  }

  handleHeaderBtnClick(btn: { isDisabled: any; value: string | number; }) {
    console.log('toolbar click: ', btn);
    if (btn.isDisabled) return;
    console.info(`toolbar btn method: ${btn.value} was triggerd!`);
    (this as any)[btn.value]();
  }

  async handleSpeedChange(speed: number) {
    this.speed = speed;
    await this.controller.simApi.simulationUpdateSpeed({
      speed,
      simulationSessionId: this.controller.sessionId,
    });
  }

  signalEmit(signalId: string) {
    this.controller.simApi.sceneSendSignalBySceneSession({
      signalId,
      sceneSessionId: this.controller.sceneId,
      simulationSessionId: this.controller.sessionId
    });
    this.signalValue = this.signalList.filter((item: any) => item.id === signalId)[0]?.name;
  }

  updateSignal(signals: SignalType[]) {
    this.signalList = signals;
  }

  clearSignal() {
    this.signalList.length = 0;
  }

  async getAndSetsignalList() {
    const { data } = await this.controller.simApi.sceneGetSignalBySceneSession({
      sceneSessionId: this.controller.sceneId,
      simulationSessionId: this.controller.sessionId,
    });
    this.signalList = []; // reset
    if (data?.data) {
      const ids = [];
      for (const s of data.data) {
        ids.push(s.id);
      }
      const modelInfos = (await this.controller.modelApi.modelInfos({
        projectId: this.controller.projectId,
        modelIds: ids
      })).data?.data;
      if (modelInfos) {
        for (const info of modelInfos) {
          if (info.hiddenStatus !== HiddenStatus.HIDDEN_IN_ENCAP) {
            this.signalList.push({ id: info.id, name: info.name });
          }
        }
      }
    }
  }

  /**
   * 工具栏：初始化
   * @returns
   */
  async initSimulation() {
    if (this.status === SimulateStatusType.initing) return;
    this.controller.serviceInit();
    this.statusChange = SimulateStatusType.initing;
    await this.controller.notifySimBackendBreakpoints();
    const simulationCheckModelChangeRes = await this.controller.simApi.simulationCheckModelChange(this.controller.projectId);
    if (simulationCheckModelChangeRes.data?.data) {
      await this.controller.autoLoadModelData();
    }
    await this.controller.simEnginInit();
  }

  async startSimulation() {
    if (this.status === "stop") {
      await this.controller.simApi.simulationResume(this.controller.sessionId);
    } else {
      await this.controller.winService.checkAllSubWinMounted();
      await this.controller.simApi.simulationStart(this.controller.sessionId);
      this.controller.consoleService.addRecord({
        level: InfoLevel.INFO,
        message: this.controller.locale.localeTrans('start_simulation'),
      });
    }
    this.statusChange = SimulateStatusType.running;
  }

  async continueSimulation() {
    if ([SimulateStatusType.pause, SimulateStatusType.stop].includes(this.status)) {
      await this.controller.simApi.simulationResume(this.controller.sessionId);
      this.statusChange = SimulateStatusType.running;
    }
  }

  async pauseSimulation() {
    await this.controller.simApi.simulationSuspend(this.controller.sessionId);
    this.statusChange = SimulateStatusType.pause;
  }

  /**
   * 处理后端主动暂停仿真的情况（例如断点触发）
   */
  backendPauseSimulation() {
    if (this.status !== SimulateStatusType.stop) {
      this.statusChange = SimulateStatusType.stop;
    }
  }

  async stepOne() {
    this.statusChange = SimulateStatusType.stop;
    if (this.firstStep) {
      await this.controller.simApi.simulationStartStep(this.controller.sessionId);
      this.firstStep = false;
    } else {
      await this.controller.simApi.simulationNext(this.controller.sessionId);
    }
  }

  async finishSimulation() {
    if (this.isSimulating()) {
      this.statusChange = SimulateStatusType.initing;
      await this.controller.simApi.simulationStop(this.controller.sessionId);
      this.simFinishUiSet();
      // 清空仿真时钟
      this.controller.clockService.clearClock();
      // 清空场景信号
      this.controller.toolbarService.clearSignal();
      // 清空确认弹窗
      app.$confirm.close();
    }
  }

  simFinishUiSet() {
    console.log('simFinishUiSet');
    this.statusChange = SimulateStatusType.finish;
    this.controller.simStatus.serviceInit();
    this.controller.sceneService.serviceInit();
    this.controller.variableService.serviceInit();
    this.controller.chartsService.serviceInit();
    this.controller.winService.closeSubWins(this.controller.winService.closeExceptWins);
    this.controller.consoleService.addRecord({
      level: InfoLevel.INFO,
      message: this.controller.locale.localeTrans('_sim_end')
    });
  }

  updateRecordStart(startTimestamp: number) {
    this.lastBeginTimeStamp = startTimestamp;
    this.controller.consoleService.addRecord({
      level: InfoLevel.INFO,
      message: this.controller.locale.localeTrans('start_simulation'),
    });
  }

  isSimulating() {
    console.log(this.status, 'yss');
    return [
      SimulateStatusType.ready,
      SimulateStatusType.running,
      SimulateStatusType.stop,
      SimulateStatusType.pause,
    ].includes(this.status);
  }

  /**
   * 获取节点步长毫秒值
   */
  getStepSpeedSM() {
    const speed = this.speed;
    // 计算公式和后端保持一致
    const interval = Math.round(5000 * ((100 - speed) / 100) + 1);
    if (interval < 100) {
      return 100;
    }
    return interval;
  }
}
